package abacab.router;

import java.util.Queue;

import abacab.actor.Actor;
import abacab.actor.ActorContextImpl;
import abacab.actor.ActorDef;
import abacab.actor.queue.QueueHandler;
import abacab.message.Envelope;
import abacab.ref.AbstractActorRef;

/**
 * The base class for any router
 * 
 * @param <M>
 *          the type of handled messages
 */
@SuppressWarnings("rawtypes")
public abstract class AbstractRouter<M> implements Router<M> {
	/** The actor system */
	private AbstractActorRef<M>	actorRef;

	/** The actor's defintion */
	private ActorDef<M>					definition;

	@Override
	public void init(AbstractActorRef<M> actorRefP, ActorDef<M> definitionP) {
		this.actorRef = actorRefP;
		this.definition = definitionP;
	}

	/**
	 * Build a new actor. The actor still needs to be initialized
	 * 
	 * @param name
	 *          the actor's name
	 * @return a new actor
	 */
	protected final Actor<M> buildActor(String name) {
		Actor<M> actor = this.definition.getBuilder().build();
		Queue<Envelope> queue = createQueueForActor();
		actor.setActorContext(new ActorContextImpl(this.actorRef, queue));
		return actor;
	}

	/**
	 * Create the queue to use for each actor. Note that this method, if overloaded, could also return the same instance for each child actor.
	 * 
	 * @return the queue to use for an actor
	 */
	protected Queue<Envelope> createQueueForActor() {
		return QueueHandler.getQueue(this.actorRef.getSystem(), this.definition.getQueueName());
	}
}